package com.witdata.framework.service.message.impl;

import com.alibaba.fastjson2.JSON;
import com.mybatisflex.core.query.QueryWrapper;
import com.witdata.mysql.base.service.SessionMessageBaseService;
import com.witdata.common.domain.Status;
import com.witdata.common.domain.dto.MessageDto;
import com.witdata.common.domain.dto.SessionDto;
import com.witdata.mysql.domain.entity.TSessionMessage;
import com.witdata.common.domain.vo.UserVo;
import com.witdata.common.exception.GlobalException;
import com.witdata.common.mapper.MessageMapper;
import com.witdata.common.domain.dto.MessageListDto;
import com.witdata.framework.service.message.SessionService;
import com.witdata.common.service.UserService;
import com.witdata.common.util.IdUtils;
import com.witdata.framework.service.message.MessageService;
import com.witdata.mqtt.service.MqttMessageSender;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class MessageServiceImpl implements MessageService {
    private final SessionMessageBaseService sessionMessageBaseService;
    private final SessionService sessionService;
    private final UserService userService;
    private final HttpServletRequest request;
    private final MqttMessageSender mqttMessageSender;

    @Override
    public MessageListDto getMessageList(Long sessionId) {
        List<TSessionMessage> tSessionMessageList = sessionMessageBaseService.list(new QueryWrapper().eq("session_id", sessionId));
        List<MessageDto> messageDtoList = MessageMapper.INSTANCE.toMessageDtoList(tSessionMessageList);
        SessionDto session = sessionService.getSession(sessionId);
        UserVo receiver = userService.getUserVoById(session.getReceiverId());
        UserVo sender = userService.getUserVoById(session.getSenderId());
        return MessageListDto.builder()
                .receiver(receiver)
                .sender(sender)
                .list(messageDtoList)
                .build();
    }

    @Transactional
    @Override
    public void sendMessage(MessageDto message) {
        TSessionMessage tSessionMessage = MessageMapper.INSTANCE.toTSessionMessage(message);
        tSessionMessage.setId(IdUtils.createId());
        tSessionMessage.setSendTime(LocalDateTime.now());
        Long userId = IdUtils.getUserIdByRequest(request);
        Long receiverId = sessionService.getReceiverIdByUserId(message.getSessionId(), userId);
        mqttMessageSender.send("/chat/message/"+receiverId, JSON.toJSONString(message));
        sessionMessageBaseService.save(tSessionMessage);
    }

    @Override
    public MessageDto getLatestMessage(Long sessionId) {
        TSessionMessage tSessionMessage = sessionMessageBaseService.getOne(new QueryWrapper().eq("session_id", sessionId).orderBy("send_time", false));
        return MessageMapper.INSTANCE.toMessageDto(tSessionMessage);
    }

    @Override
    public Long getUnreadCounts(Long sessionId, Long senderId) {
        return sessionMessageBaseService.count(
                new QueryWrapper().eq("session_id", sessionId)
                        .eq("sender_id",senderId)
                        .eq("read_state",false)
        );
    }

    @Override
    public void readMessage(Long sessionId, Long senderId) {
        TSessionMessage tSessionMessage = TSessionMessage.builder()
                .readState(true)
                .build();
        tSessionMessage.setReadState(true);
        boolean updated = sessionMessageBaseService.update(tSessionMessage,
                new QueryWrapper().eq("session_id", sessionId)
                        .eq("sender_id", senderId)
        );
        if (!updated) throw new GlobalException(Status.READERROR);
    }
}
